﻿using System;
using System.Collections.Generic;
using Dsl.Ped.AddIn.Java.Generated.Interfaces;
using Dsl.Ped.AddIn.Java.Helpers;
using Dsl.Ped.AddIn.Java.Resources;
using Dsl.Ped.Common.Commands;
using Dsl.Ped.Framework.Common;
using Dsl.Ped.AddIn.Java.Projections.ClassTextProjection;
using Dsl.Ped.Framework.Messages;
using Dsl.Ped.Framework.Projections;
using Dsl.Ped.Framework.Projectives;
using System.ComponentModel;

namespace Dsl.Ped.AddIn.Java.Generated
{
    /// <summary>
    /// This is the class that enhances the <see cref="Class"/> class 
    /// provided in the model of projections, these are organized into containers
    /// </summary>
    public partial class Class : IProjective, IDataErrorInfo
    {
        /// <summary>
        /// Gets the projection containers of the <see cref="Class"/> class
        /// </summary>
        /// <returns>Projection containers of the <see cref="Class"/> class</returns>
        public List<IProjectionContainer> GetProjectionContainers()
        {
            List<IProjectionContainer> projectionContainers = new List<IProjectionContainer>();
            projectionContainers.Add(new ProjectionContainer("Class")
                .RegisterProjection("wholeClass", new ClassTextProjection(
                    this,
                    new ObjectProjective(new List<IProjectionContainer>() { 
                        new ProjectionContainer("Members")
                            .RegisterProjection("members", CollectionProjectionFactory.GetVerticalProjection<Member>(members, items => true, 
                                vp =>
                                {
                                    vp.RemoveItem = member => 
                                        members.Remove(member as Member);
                                })),
                    }),
                    new List<IMenuCommand>() { 
                        new MenuCommand("New Field", () => this.members.Insert(0, new Field() { type = "Int", name = "Field" })),
                        new MenuCommand("New Constructor", () => this.members.Insert(0, new Constructor() { name = this.name })),
                        new MenuCommand("New Method", () => this.members.Insert(0, new Method() { name = "Method" }))
                    },
                    () => this.members.RemoveAt(members.Count - 1))));
            projectionContainers.Add(new ProjectionContainer("Only Variables")
                .RegisterProjection("onlyVariables", CollectionProjectionFactory.GetVerticalProjection<Member>(members, (member) =>
                    {
                        return member is IVariable;
                    })));
            projectionContainers.Add(new ProjectionContainer("JustName1")
                .RegisterProjection("justname", ObjectProjectionFactory.GetHeaderedProjection("name: ", ValueProjectionFactory.GetTextBoxProjection(this, typeof(string), "name"))));
            projectionContainers.Add(
                new ProjectionContainer("Plain Text") { ForceRefresh = true }
                    .RegisterProjection(
                        "PlainText",
                        TextProjectionFactory.GetSyntaxHighlighterProjection(
                            this, ConvertMe, sh => { 
                                sh.KeyWords = JavaResources.GetKeyWords();
                                sh.KeyWordsDelimiter = JavaResources.KeyWordsDelimiter;
                            })));

            return projectionContainers;
        }

        private string ConvertMe(object obj)
        {
            int tabsCount = 3;
            var tabSpace = new string(' ', tabsCount);

            var javaClass = (Class)obj;
            var strClass = ClassHelper.ToPlainText(javaClass);

            var result = strClass.Replace("\t", tabSpace);
            return result;
        }

        #region IDataErrorInfo Members

        public string Error
        {
            get
            {
                throw new NotImplementedException();
            }
        }
       
        public string this[string propertyName]
        {
            get
            {
                string validationResult;
                switch (propertyName)
                {
                    case "name":
                        validationResult = validateName();
                        var messenger = FrameworkMessenger.GetMessenger(this);
                        if (messenger != null)messenger.Send(new NotifyMessage(this, propertyName, validationResult, NotifyType.Error));
                        break;
                    case "superclass":
                        validationResult = validateSuperclass();
                        var messenger2 = FrameworkMessenger.GetMessenger(this);
                        if (messenger2 != null) messenger2.Send(new NotifyMessage(this, propertyName, validationResult, NotifyType.Info));
                        break;
                    default:
                        throw new ApplicationException("Unknown Property being validated.");
                }

                return validationResult;
            }
        }

        private string validateName()
        {
            return (String.IsNullOrEmpty(this.name)) ? "Class name must be specified" : String.Empty;
        }

        private string validateSuperclass()
        {
            return (String.IsNullOrEmpty(this.superclass)) ? "Superclass name must be specified" : String.Empty;
        }

        #endregion
    }
}
